home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
eulisp
/
mpfeel.lha
/
MPFeel
/
class.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-06
|
43KB
|
1,627 lines
/* ******************************************************************** */
/* class.c Copyright (C) Codemist and University of Bath 1989 */
/* */
/* classes */
/* ******************************************************************** */
/*
* $Id: class.c,v 1.11 1992/03/14 14:33:48 pab Exp $
*
* $Log: class.c,v $
* Revision 1.11 1992/03/14 14:33:48 pab
* side efects return values
*
* Revision 1.10 1992/02/27 15:46:57 pab
* bytecode + error changes
*
* Revision 1.9 1992/01/29 13:39:10 pab
* Fixed gc bug
*
* Revision 1.8 1992/01/22 13:29:49 pab
* Fixed GC bug
*
* Revision 1.7 1992/01/17 22:28:06 pab
* Removed defstruct + defclass 'cos
* no one used them
*
* Revision 1.6 1992/01/09 22:28:46 pab
* Fixed for low tag ints
*
* Revision 1.5 1992/01/05 22:47:57 pab
* Minor bug fixes, plus BSD version
*
* Revision 1.4 1991/12/22 15:13:56 pab
* Xmas revision
*
* Revision 1.3 1991/11/15 13:44:31 pab
* copyalloc rev 0.01
*
* Revision 1.2 1991/09/11 12:07:05 pab
* 11/9/91 First Alpha release of modified system
*
* Revision 1.1 1991/08/12 16:49:30 pab
* Initial revision
*
* Revision 1.10 1991/06/17 19:05:23 pab
* altered set_assoc to eval properly.
*
* Revision 1.8 1991/02/13 18:18:53 kjp
* Pass.
*
*/
#define KJPDBG(x)
#define INOUT(x)
#define CLASSBUG(x) /* fprintf(stderr,"CLASSBUG:");x;fflush(stderr) */
/*
* Change Log:
* Version 1, June 1989
* Version N ( N >> 1 ), November 1989
*/
#include <stdio.h>
#include "defs.h"
#include "structs.h"
#include "funcalls.h"
#include "global.h"
#include "error.h"
#include "class.h"
#include "vectors.h"
#include "table.h"
#include "bootstrap.h"
#include "slots.h"
#include "ngenerics.h"
#include "modules.h"
#include "modboot.h"
#include "symboot.h"
#include "garbage.h"
#define CLASSES_ENTRIES 61
MODULE Module_classes;
LispObject Module_classes_values[CLASSES_ENTRIES];
#define is_class(c) (typeof(c) == TYPE_CLASS)
#define MYCONS(a,b) EUCALL_2(Fn_cons,a,b)
extern LispObject Basic_Structure;
extern LispObject Primitive_Class;
extern void set_anon_associate(LispObject*,LispObject,LispObject);
/* Internal symbols... */
static LispObject sym_direct_superclasses;
static LispObject sym_direct_slot_descriptions;
static LispObject sym_metaclass_hypotheses;
static LispObject sym_slot_class;
static LispObject sym_slot_initargs;
static LispObject sym_predicate;
/* Functions... */
LispObject Fn_make_predicate(LispObject*);
/*
* These are the class object accessor functions.
* At level-1 or above, most of these must be generic but at level-0
* it is unnecesary
*
* All of the below assumes single inheritance - must change any piece
* of generic code referencing CLASS.superclass
*/
EUFUN_1( Fn_classp, class)
{
LispObject Fn_subclassp(LispObject*);
RETURN_EUCALL(EUCALL_2(Fn_subclassp,classof(class),Standard_Class));
}
EUFUN_CLOSE
EUFUN_1( Fn_class_of, object)
{
return(classof(object));
}
EUFUN_CLOSE
EUFUN_2( Fn_subclassp, sub, class)
{
LispObject walker;
if (sub == nil) return(nil);
if (sub == class) return(sub); /* Used to say lisptrue which is wrong */
walker = sub->CLASS.superclasses;
while(is_cons(walker)) {
STACK_TMP(CDR(walker));
if (EUCALL_2(Fn_subclassp,CAR(walker),ARG_1(stackbase)) != nil)
return(ARG_0(stackbase));
else
UNSTACK_TMP(walker);
}
return(nil);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_name, class)
{
if (EUCALL_2(Fn_subclassp,classof(class),Standard_Class) == nil)
CallError(stacktop,"class-name: not a class",ARG_0(stackbase),NONCONTINUABLE);
return(ARG_0(stackbase)->CLASS.name);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_precedence_list, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"class-precedence-list: non class",class,NONCONTINUABLE);
return(class->CLASS.precedence);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_prototype, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,"class-prototype: not a class",class,NONCONTINUABLE);
fprintf(stderr,"Class-prototype: No such function\n");
return nil;
}
EUFUN_CLOSE
LispObject generic_compute_class_precedence_list;
EUFUN_1( Gf_compute_class_precedence_list, c)
{
return(generic_apply_1(stacktop,generic_compute_class_precedence_list,c));
}
EUFUN_CLOSE
EUFUN_1( Md_compute_class_precedence_list_Class, class)
{
LispObject walker,result;
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"compute-class-precedence-list: non class",class,NONCONTINUABLE);
walker = class; result = nil;
while (walker != nil) {
LispObject super, xx;
STACK_TMP(walker);
STACK_TMP(result);
EUCALLSET_2(xx, Fn_cons, walker, nil);
UNSTACK_TMP(result);
EUCALLSET_2(result, Fn_nconc, result, xx);
UNSTACK_TMP(walker);
super = walker->CLASS.superclasses;
if (super == nil)
walker = nil;
else if (is_cons(CDR(super)))
CallError(stacktop,"compute-class-precedence-list: mi class",class,
NONCONTINUABLE);
else
walker = CAR(super);
}
return(result);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_direct_superclasses, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"class-direct-superclasses: non class",class,NONCONTINUABLE);
return(class->CLASS.superclasses);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_direct_subclasses, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"class-direct-subclasses: non class",class,NONCONTINUABLE);
return(class->CLASS.subclasses);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_slot_descriptions, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"class-slot-descriptions: non class",class,NONCONTINUABLE);
return(class->CLASS.slot_list);
}
EUFUN_CLOSE
EUFUN_1( Fn_class_direct_slot_descriptions, class)
{
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,
"class-slot-descriptions: non class",class,NONCONTINUABLE);
/* HACK !!! Wrong !! */
return(class->CLASS.direct_slot_list);
}
EUFUN_CLOSE
/*
* Slot access protocol...
*/
/* Generic slot-value-using-class */
LispObject generic_slot_value_using_class;
EUFUN_3( Gf_slot_value_using_class, c, o, p)
{
return(generic_apply_3(stacktop,generic_slot_value_using_class,c,o,p));
}
EUFUN_CLOSE
EUFUN_3( Md_slot_value_using_class_Structure_Class, class, obj, pos)
{
return(slotref(obj,intval(pos)));
}
EUFUN_CLOSE
EUFUN_3( Md_slot_value_using_class_Standard_Class, class, obj, pos)
{
return(slotref(obj,intval(pos)));
}
EUFUN_CLOSE
LispObject generic_slot_value_using_class_setter;
/* You know, some people actually USE the value of these things :-( */
EUFUN_4( Md_slot_value_using_class_setter_Structure_Class, class, obj, pos, val)
{
LispObject tmp;
slotrefupdate(obj,intval(pos),val);
return val;
}
EUFUN_CLOSE
EUFUN_4( Md_slot_value_using_class_setter_Standard_Class, class, obj, pos, val)
{
slotrefupdate(obj,intval(pos),val);
return val;
}
EUFUN_CLOSE
LispObject generic_slot_value_using_slot_description;
EUFUN_2( Md_slot_value_using_slot_description_Local_Slot_Description,
obj, desc)
{
LispObject xx;
EUCALLSET_1(xx, Fn_class_of, obj); /* CANNOT GC */
return(generic_apply_3(stacktop,generic_slot_value_using_class,
xx,
obj,
slot_desc_position(desc)));
}
EUFUN_CLOSE
LispObject generic_slot_value_using_slot_description_setter;
EUFUN_3(
Md_slot_value_using_slot_description_setter_Local_Slot_Description,
obj, desc, val)
{
LispObject xx;
EUCALLSET_1(xx, Fn_class_of, obj); /* CANNOT GC */
return(generic_apply_4(stacktop,generic_slot_value_using_class_setter,
xx, obj, slot_desc_position(desc), val));
}
EUFUN_CLOSE
LispObject generic_find_slot_description;
EUFUN_2( Gf_find_slot_description, c, n)
{
return(generic_apply_2(stacktop,generic_find_slot_description,c,n));
}
EUFUN_CLOSE
EUFUN_2( Md_find_slot_description_Structure_Class, class, name)
{
LispObject desc;
EUCALLSET_2(desc, Fn_find_slot_description,class,name);
if (desc == nil)
CallError(stacktop,
"find-slot-description: slot missing",
ARG_1(stackbase),NONCONTINUABLE);
return(desc);
}
EUFUN_CLOSE
EUFUN_2( Md_find_slot_description_Standard_Class, class, name)
{
LispObject desc;
EUCALLSET_2(desc, Fn_find_slot_description,class,name);
if (desc == nil)
CallError(stacktop,"find-slot-description: slot missing",
ARG_1(stackbase),NONCONTINUABLE);
return(desc);
}
EUFUN_CLOSE
EUFUN_2( Fn_slot_value, obj, slotname)
{
LispObject desc;
LispObject xx;
xx=classof(obj);
desc = generic_apply_2(stacktop,generic_find_slot_description,
xx, slotname);
return(generic_apply_2(stacktop,generic_slot_value_using_slot_description,
ARG_0(stackbase),desc));
}
EUFUN_CLOSE
EUFUN_3( Fn_slot_value_setter, obj, slotname, val)
{
LispObject desc;
LispObject xx;
xx=classof(obj);
desc = generic_apply_2(stacktop,generic_find_slot_description,
xx, slotname);
return(generic_apply_3(stacktop,
generic_slot_value_using_slot_description_setter,
ARG_0(stackbase),desc,ARG_2(stackbase)));
}
EUFUN_CLOSE
/*
* The inheritance protocol...
*/
EUFUN_3( Fn_add_superclasses, class, supers, slotsinitargs)
{
LispObject walker,xx;
/* fprintf(stderr,"add-supers: \n"); fflush(stderr); */
if (typeof(class) != TYPE_CLASS)
CallError(stacktop,"add-superclasses: non class",class,NONCONTINUABLE);
if (EUCALL_2(Fn_subclassp,classof(class),Standard_Class) == nil)
CallError(stacktop,"add-superclasses: non structure-class",
class,NONCONTINUABLE);
/* Perform the 'add-subclass' calls on the supers - checks compatability */
/* Backtracking's a problem... */
walker = supers;
while (is_cons(walker)) {
STACK_TMP(CDR(walker));
EUCALL_2(Fn_add_subclass,ARG_0(stackbase),CAR(walker));
UNSTACK_TMP(walker);
}
/* Do precedence list... */
class = ARG_0(stackbase);
EUCALLSET_1(xx,
Gf_compute_class_precedence_list,class);
ARG_0(stackbase)->CLASS.precedence=xx;
class = ARG_0(stackbase); slotsinitargs=ARG_2(stackbase);
EUCALL_2(Fn_collect_slots,class,slotsinitargs);
return(ARG_0(stackbase));
}
EUFUN_CLOSE
EUFUN_2( Fn_add_subclass, class, super)
{
extern LispObject Fn_nconc(LispObject*);
LispObject xx;
/* fprintf(stderr,"add-sub: \n"); fflush(stderr); */
if (EUCALL_2(Fn_metaclass_compatibility,class,super) == nil)
CallError(stacktop,
"add-subclass: incompatible metaclasses",super,NONCONTINUABLE);
/* Just mark the new class - change the existing ones later */
super = ARG_1(stackbase);
EUCALLSET_2(xx,Fn_cons,super,nil);
class = ARG_0(stackbase);
EUCALLSET_2(xx,Fn_nconc,class->CLASS.superclasses,xx);
class = ARG_0(stackbase);
class->CLASS.superclasses = xx;
super = ARG_1(stackbase);
class->CLASS.local_count = super->CLASS.local_count;
/* If we're all must have gone OK so now mark the existing class(es) */
/* Should be in a less haphazard order for multiple inheritance !! */
EUCALLSET_2(xx, Fn_cons, class, super->CLASS.subclasses);
super = ARG_1(stackbase);
super->CLASS.subclasses = xx;
class = ARG_0(stackbase);
return(class);
}
EUFUN_CLOSE
EUFUN_2( Fn_metaclass_compatibility, class, super)
{
/* fprintf(stderr,"compatability: \n"); fflush(stderr); */
if (!is_class(class))
CallError(stacktop,
"metaclass-compatibility: non class",class,NONCONTINUABLE);
if (!is_class(super))
CallError(stacktop,
"metaclass-compatibility: non class",super,NONCONTINUABLE);
RETURN_EUCALL(EUCALL_2(Fn_subclassp,classof(class),classof(super)));
}
EUFUN_CLOSE
LispObject generic_add_slot_description;
EUFUN_2( Gf_add_slot_description, c, desc)
{
return(generic_apply_2(stackbase,generic_add_slot_description,c,desc));
}
EUFUN_CLOSE
EUFUN_2( Md_add_slot_description_Class_Slot_Description, class, desc)
{
LispObject xx;
if (class->CLASS.slot_table == nil) {
(ARG_0(stackbase))->CLASS.slot_table =
(LispObject) allocate_table(stacktop,Fn_eq);
class = ARG_0(stackbase);
desc=ARG_1(stackbase);
}
EUCALL_3(tref_updator,class->CLASS.slot_table,
slot_desc_name(desc),desc);
class = ARG_0(stackbase);
desc = ARG_1(stackbase);
EUCALLSET_2(xx,Fn_cons,desc,class->CLASS.slot_list);
class = ARG_0(stackbase);
class->CLASS.slot_list = xx;
return(class);
}
EUFUN_CLOSE
EUFUN_2( Md_add_slot_description_Class_Local_Slot_Description, class, desc)
{
if (slot_desc_position(desc) == unbound)
{
int n;
n=(class->CLASS.local_count++);
slot_desc_position(desc) = allocate_integer(stacktop,n);
class=ARG_0(stackbase);
desc=ARG_1(stackbase);
}
RETURN_EUCALL(EUCALL_2(Md_add_slot_description_Class_Slot_Description,class,desc));
}
EUFUN_CLOSE
static LispObject find_superclass_slot_description(LispObject *stacktop,
LispObject c,
LispObject name)
{
LispObject walker,desc;
walker = c->CLASS.superclasses;
while (is_cons(walker)) {
STACK_TMP(CDR(walker));
STACK_TMP(name);
EUCALLSET_2(desc, Fn_find_slot_description,CAR(walker),name);
if (desc != nil) return(desc);
UNSTACK_TMP(name);
UNSTACK_TMP(walker);
}
return(nil);
}
static LispObject superclass_slot_descriptions(LispObject *stacktop,LispObject c)
{
extern EUDECL( Fn_append);
LispObject all,walker;
STACK_TMP(c);
walker = c->CLASS.superclasses; all = nil;
while(is_cons(walker)) {
all = EUCALL_2(Fn_append,all,CAR(walker)->CLASS.slot_list);
walker = CDR(walker);
}
UNSTACK_TMP(c);
return(all);
}
EUFUN_2( Fn_collect_slots, class, slots_initlist)
{
LispObject allslots = nil;
if (!is_class(class))
CallError(stacktop,"collect-slots: non class",class,NONCONTINUABLE);
if (EUCALL_2(Fn_subclassp,classof(class),Standard_Class) == nil)
CallError(stacktop,"collect-slots: non class",class,NONCONTINUABLE);
/* Collect the slots in such a way that for simple single
inheritance, slot position is preserved... */
/* Bleargh!! Make the slots referenced in the initlist */
while (is_cons(slots_initlist)) {
LispObject desc;
STACK_TMP(CDR(slots_initlist));
class=ARG_0(stackbase);
EUCALLSET_2(desc,Gf_make_slot_description,class,CAR(slots_initlist));
class=ARG_0(stackbase);
EUCALL_2(Gf_add_slot_description,class,desc);
UNSTACK_TMP(slots_initlist);
}
/* Now do any as yet uninherited... */
allslots = superclass_slot_descriptions(stacktop,ARG_0(stackbase)/*class*/);
class=ARG_0(stackbase);
while (is_cons(allslots)) {
LispObject newdesc,oldesc;
STACK_TMP(CDR(allslots));
oldesc = CAR(allslots);
STACK_TMP(oldesc);
EUCALLSET_2(newdesc,Fn_find_slot_description,
class,slot_desc_name(oldesc));
UNSTACK_TMP(oldesc);
if (newdesc == nil) {
EUCALLSET_3(newdesc, Gf_make_inherited_slot_description,
class,oldesc,nil);
class=ARG_0(stackbase);
EUCALL_2(Gf_add_slot_description,class,newdesc);
}
UNSTACK_TMP(allslots);
class=ARG_0(stackbase);
}
return(class);
}
EUFUN_CLOSE
LispObject generic_make_slot_description;
EUFUN_2( Gf_make_slot_description, c, l)
{
return(generic_apply_2(stacktop,generic_make_slot_description,c,l));
}
EUFUN_CLOSE
EUFUN_2( Md_make_slot_description_Class, class, plist)
{
LispObject desc,slot_name,slot_class;
LispObject ret,xx;
/* Search the initargs for specified... else default */
slot_name = search_keylist(stacktop,plist,sym_name);
if (slot_name == unbound)
CallError(stacktop,"make-slot-description: slot name missing",plist,NONCONTINUABLE);
STACK_TMP(slot_name);
desc = find_superclass_slot_description(stacktop,class,slot_name);
if (desc != nil) {
class=ARG_0(stackbase);
plist=ARG_1(stackbase);
RETURN_EUCALL(EUCALL_3(Gf_make_inherited_slot_description,class
,desc,plist));
}
UNSTACK_TMP(slot_name);
plist=ARG_1(stackbase);
slot_class = search_keylist(stacktop,plist,sym_slot_class);
if (slot_class == unbound)
CallError(stacktop,"make-slot-description: missing slot class ",
plist,NONCONTINUABLE);
/* Generate the position as necessary */
if (EUCALL_2(Fn_subclassp,slot_class,Slot_Description) == nil)
CallError(stacktop,"make-slot-description: invalid slot class",
slot_class,NONCONTINUABLE);
/* Something of a hack but still... */
EUCALLSET_2(ret,Gf_make_instance,slot_class,plist);
class=ARG_0(stackbase);
STACK_TMP(ret);
xx=MYCONS(ret,class->CLASS.direct_slot_list);
UNSTACK_TMP(ret);
class=ARG_0(stackbase);
class->CLASS.direct_slot_list = xx;
return(ret);
}
EUFUN_CLOSE
LispObject generic_make_inherited_slot_description;
EUFUN_3( Gf_make_inherited_slot_description, c, d, l)
{
return(generic_apply_3(stacktop,generic_make_inherited_slot_description,c,d,l));
}
EUFUN_CLOSE
EUFUN_3( Md_make_inherited_slot_description_Class_Slot_Description, class, oldesc, plist)
{
extern LispObject generic_allocate_instance;
LispObject slot_class;
LispObject newdesc;
IGNORE(class); /* Strange but true... */
slot_class = classof(oldesc);
newdesc = generic_apply_2(stacktop,generic_allocate_instance,slot_class,nil);
EUCALLSET_3(newdesc, Fn_inherit_slot_details,
newdesc,/*oldesc*/ARG_1(stackbase),/*plist*/ARG_2(stackbase));
return(newdesc);
}
EUFUN_CLOSE
EUFUN_3( Fn_inherit_slot_details, newdesc, oldesc, plist)
{
LispObject modifier;
/* Should be generic I suppose */
/* For local slot descriptions */
if (EUCALL_2(Fn_subclassp,classof(newdesc),Slot_Description) == nil)
CallError(stacktop,"inherit-slot-details: non local slot description",
newdesc,NONCONTINUABLE);
if (EUCALL_2(Fn_subclassp,classof(oldesc),Slot_Description) == nil)
CallError(stacktop,"inherit-slot-details: non local slot description",
oldesc,NONCONTINUABLE);
/* All local - all cool... */
/* Inherit as is - modify as necessary */
/* Merge initargs... */
slot_desc_initargs(newdesc) = slot_desc_initargs(oldesc);
modifier = search_keylist(stacktop,plist,sym_initargs);
if (modifier != unbound) {
if (slot_desc_initargs(oldesc) == unbound)
slot_desc_initargs(newdesc) = modifier;
else
EUCALLSET_2(slot_desc_initargs(newdesc),
Fn_nconc,modifier,slot_desc_initargs(newdesc));
}
/* Merge initforms... */
slot_desc_initform(newdesc) = slot_desc_initform(oldesc);
modifier = search_keylist(stacktop,plist,sym_initform);
if (modifier != unbound) slot_desc_initform(newdesc) = modifier;
/* Just take name and position direct at level-0 */
slot_desc_name(newdesc) = slot_desc_name(oldesc);
slot_desc_position(newdesc) = slot_desc_position(oldesc);
slot_desc_mutable(newdesc) = slot_desc_mutable(oldesc);
return(newdesc);
}
EUFUN_CLOSE
/*
* Instance generation...
*/
/* GENERIC FUNCTION 'allocate_instance' */
LispObject generic_allocate_instance;
/* Standard-Class */
EUFUN_2( Md_allocate_instance_1, class, initlist)
{
LispObject new;
IGNORE(initlist);
if (EUCALL_2(Fn_subclassp,class,Standard_Class) != nil) {
new = (LispObject) allocate_class(stacktop,class);
STACK_TMP(new);
new->CLASS.slot_table = (LispObject) allocate_table(stacktop,Fn_eq);
UNSTACK_TMP(new);
}
else {
new = (LispObject) allocate_instance(stacktop,class);
}
return(new);
}
EUFUN_CLOSE
/* Structure-Class */
EUFUN_2( Md_allocate_instance_2, class, initlist)
{
LispObject inst;
inst = (LispObject) allocate_instance(stacktop,class);
class=ARG_0(stackbase);
{
int i;
for(i=0; i<class->CLASS.local_count; i++)
slotref(inst,i) = unbound;
}
return(inst);
}
EUFUN_CLOSE
/* Slot_Description_Class */
EUFUN_2( Md_allocate_instance_3, class, initlist)
{
LispObject inst;
inst = (LispObject) allocate_instance(stacktop,class);
slot_desc_mutable(inst) = lisptrue;
{
int i;
for(i=0; i<class->CLASS.local_count; i++)
slotref(inst,i) = unbound;
}
return(inst);
}
EUFUN_CLOSE
extern LispObject Condition_Class;
/* Condition-Class */
EUFUN_2( Md_allocate_instance_4, class, initlist)
{
LispObject cond;
cond = (LispObject) allocate_instance(stacktop,class);
{
int i;
for(i=0; i<class->CLASS.local_count; i++)
slotref(cond,i) = unbound;
}
return(cond);
}
EUFUN_CLOSE
/* Primitive classes */
EUFUN_2( Md_allocate_instance_Primitive_Class, c, l)
{
CallError(stacktop,"allocate-instance: can't allocate primitive",c,NONCONTINUABLE);
return(nil);
}
EUFUN_CLOSE
EUFUN_3( Fn_fill_slot, desc, obj, initlist)
{
LispObject initargs,key,value = unbound;
if (EUCALL_2(Fn_subclassp,classof(desc),Slot_Description) == nil)
CallError(stacktop,"fill-slot: invalid slot description",desc,NONCONTINUABLE);
initargs = slot_desc_initargs(desc);
while(is_cons(initargs)) {
key = CAR(initargs); initargs = CDR(initargs);
value = search_keylist(stacktop,initlist,key);
if (value != unbound) break;
}
if (value != unbound) {
(void) generic_apply_3(stacktop,generic_slot_value_using_slot_description_setter,
obj,desc,value);
}
else {
if (slot_desc_initform(desc) != unbound) {
LispObject xx;
extern LispObject Fn_apply(LispObject*);
EUCALLSET_2(xx, Fn_apply,slot_desc_initform(desc),nil);
(void) generic_apply_3(stacktop,generic_slot_value_using_slot_description_setter,
ARG_1(stackbase)/*obj*/,ARG_0(stackbase)/*desc*/,
xx);
/* Should be other... */
}
}
return(ARG_1(stackbase));
}
EUFUN_CLOSE
/* GENERIC FUNCTION 'initialize_instance' */
LispObject generic_initialize_instance;
/* Object */
EUFUN_2( Md_initialize_instance_1, obj, initlist)
{
LispObject class = classof(obj);
LispObject local_slots;
CLASSBUG(fprintf(stderr,"init-inst: structure\n"));
/* OK - initialize strategy is - take each local slot in turn.
get it's instance description.
if it has initargs, search the initlist.
failing that use initform.
failing THAT leave unbound. */
/* Should get a more efficient table stepper one day but ... */
EUCALLSET_1(local_slots, Fn_class_slot_descriptions,class);
/* Tryin' it with all slots */
while (local_slots != nil) {
LispObject desc = CAR(local_slots);
CLASSBUG(fprintf(stderr,"init-inst: structure, filling...\n"));
STACK_TMP(CDR(local_slots));
obj=ARG_0(stackbase); initlist=ARG_1(stackbase);
EUCALL_3(Fn_fill_slot,desc,obj,initlist);
UNSTACK_TMP(local_slots);
}
obj=ARG_0(stackbase);
return(obj);
}
EUFUN_CLOSE
/* Standard-Class */
EUFUN_2( Md_initialize_instance_2, obj, initlist)
{
LispObject name,superclass,slot_descriptions;
obj=EUCALL_2(Md_initialize_instance_1,obj,initlist); /* Other slots... */
initlist=ARG_1(stackbase);
name = search_keylist(stacktop,initlist,sym_name);
if (name == unbound) name = sym_anonymous_class;
superclass = search_keylist(stacktop,initlist,sym_direct_superclasses);
ARG_0(stackbase)=obj;
if (superclass == unbound)
{
STACK_TMP(name);
STACK_TMP(superclass);
EUCALLSET_2(superclass, Fn_cons,Object,nil);
UNSTACK_TMP(superclass);
UNSTACK_TMP(name);
}
if (!is_cons(superclass))
CallError(stacktop,"initialize-instance: bad superclasses",
superclass,NONCONTINUABLE);
obj=ARG_0(stackbase); initlist=ARG_1(stackbase);
slot_descriptions = search_keylist(stacktop,initlist,sym_direct_slot_descriptions);
if (slot_descriptions == unbound) slot_descriptions = nil;
/* Do inheritance & initialization */
obj->CLASS.name = name;
/* These don't do what they're supposed to */
/* In fact currently they just add the parent/children info */
EUCALL_3(Fn_add_superclasses,obj,superclass,slot_descriptions);
obj=ARG_0(stackbase);
return(obj);
}
EUFUN_CLOSE
/* Slot_Description */
EUFUN_2( Md_initialize_instance_3, obj, initlist)
{
LispObject name,position,initargs,initform,mutable;
name = search_keylist(stacktop,initlist,sym_name);
if (name == unbound)
CallError(stacktop,"initialize-instance: no name for slot description",
unbound,NONCONTINUABLE);
position = search_keylist(stacktop,initlist,sym_position);
initargs = search_keylist(stacktop,initlist,sym_initargs);
initform = search_keylist(stacktop,initlist,sym_initform);
mutable = search_keylist(stacktop,initlist,sym_mutable);
/* Should verify... */
slot_desc_name(obj) = name;
slot_desc_position(obj) = position;
slot_desc_initargs(obj) = initargs;
slot_desc_initform(obj) = initform;
slot_desc_mutable(obj) = (mutable == nil ? nil : lisptrue);
RETURN_EUCALL(EUCALL_2(Md_initialize_instance_1,obj,initlist));
}
EUFUN_CLOSE
extern LispObject Default_Condition;
/* Default-Condition */
EUFUN_2( Md_initialize_instance_4, obj, initlist)
{
LispObject message,value;
message = search_keylist(stacktop,initlist,sym_message);
if (message == unbound) message = nil;
value = search_keylist(stacktop,initlist,sym_error_value);
condition_message(obj) = message;
condition_error_value(obj) = value;
RETURN_EUCALL(EUCALL_2(Md_initialize_instance_1,obj,initlist));
}
EUFUN_CLOSE
/* A would-be generic... */
EUFUN_2( Gf_make_instance, class, initargs)
{
LispObject obj;
obj = generic_apply_2(stacktop,generic_allocate_instance,class,initargs);
initargs=ARG_1(stackbase);
obj = generic_apply_2(stackbase,generic_initialize_instance,obj,initargs);
return(obj);
}
EUFUN_CLOSE
/*
* The defstruct stuff...
*/
/* Keylist utilities... */
/* Searches through alternating symbol/value slot option lists for opname */
LispObject search_option(LispObject opname,LispObject oplist)
{
if (oplist == nil) return(unbound);
if (CAR(oplist) == opname) return(CAR(CDR(oplist)));
return(search_option(opname,CDR(CDR(oplist))));
}
/* Does the same thing more robustly... */
LispObject search_keylist(LispObject *stacktop,LispObject list,LispObject key)
{
int i=0;
LispObject ptr;
if (list != nil && !is_cons(list))
CallError(stacktop,"invalid key list",list,NONCONTINUABLE);
ptr=list;
while (ptr!=nil)
{ i++;
ptr=CDR(ptr);
}
if (i%2 != 0)
CallError(stacktop,"unbalanced initlist",list,NONCONTINUABLE);
while(list != nil) {
LispObject lkey = CAR(list);
LispObject lval = CAR(CDR(list));
if (key == lkey) return(lval);
list = CDR(CDR(list));
}
return(unbound);
}
extern LispObject canonical_slot_initargs(LispObject*);
/* Sets up the canonical form and verifies */
EUFUN_3( canonical_slot_initargs, mod, env, slotspec)
{
return nil;
}
EUFUN_CLOSE
/*
* Various class / slot utilities...
*/
EUFUN_1( Fn_local_slots, class)
{
LispObject i_d;
i_d = class->CLASS.slot_table;
if (i_d == nil) return(nil); /* No slots at all */
if (is_table(i_d)) {
LispObject local = nil,all;
EUCALLSET_1(all, Fn_table_parameters,i_d);
while (all!=nil) {
STACK_TMP(CDR(all));
if (EUCALL_2(Fn_subclassp,classof(CAR(all)),Local_Slot_Description) != nil) {
local = MYCONS(CAR(all),local);
}
UNSTACK_TMP(all);
}
return(local);
}
CallError(stacktop,"as yet unimplemented instance_description type",class,
NONCONTINUABLE);
return(nil); /* Dummy */
}
EUFUN_CLOSE
EUFUN_2( Fn_mutable_slot_p, object, slot )
{
STUB("mutable-slot-p");
return(lisptrue);
}
EUFUN_CLOSE
EUFUN_2( Fn_slot_exists_p, object, slotname )
{
LispObject class = classof(object);
/* May have to genericise it later */
if ( TREF(CLASS_DESCS(class),slotname) != nil ) {
return(slotname);
}
else {
return(nil);
}
}
EUFUN_CLOSE
EUFUN_2( Fn_slot_bound_p, object, slotname)
{
if (EUCALL_2(Fn_slot_exists_p,object,slotname) == nil) {
signal_message(stacktop,SLOT_MISSING,"slot-bound-p",slotname);
/* CallError(stacktop,"slot-missing",slotname,NONCONTINUABLE); */
}
if (EUCALL_2(Fn_slot_value,object,slotname) == unbound) {
return(nil);
}
else {
return(slotname);
}
}
EUFUN_CLOSE
EUFUN_1( Fn_slot_description_readers, desc)
{
STUB("slot-description-readers");
return(nil);
}
EUFUN_CLOSE
EUFUN_1( Fn_slot_description_writers, desc)
{
STUB("slot-description-writers");
return(nil);
}
EUFUN_CLOSE
/*
* Constructor / accessor generation.
*
* These are set out in the C equivalent of...
*
* (defun make-reader (class slot-name)
* (let ((pos (slot-description-position
* (find-slot-description class slot-name))))
* (lambda (obj) (slot-value-using-class class obj pos))))
*
* ... or some such. All accessors have their home in the same module.
* (That module being 'classes' for now)
*/
static EUFUN_2( constructor_template, env, initlist)
{
RETURN_EUCALL(EUCALL_2(Gf_make_instance,symbol_ref(stacktop,NULL,env,sym_class),initlist));
}
EUFUN_CLOSE
EUFUN_1( Fn_make_constructor, class)
{
return(make_anonymous_module_env_function_1(stacktop,
(LispObject) &Module_classes,
constructor_template,
-1,sym_class,class));
}
EUFUN_CLOSE
/* Template for structure-class metainstances... */
EUFUN_2( structure_reader_template, env, obj)
{
if (EUCALL_2(Fn_subclassp,classof(obj),
symbol_ref(stacktop,NULL,env,sym_class)) == nil)
CallError(stacktop,"wrong class of object for reader",obj,NONCONTINUABLE);
return(slotref(obj,intval(symbol_ref(stacktop,NULL,env,sym_position))));
}
EUFUN_CLOSE
/* Anything template */
EUFUN_2( reader_template, env, obj)
{
RETURN_EUCALL(EUCALL_2(Fn_slot_value,obj,((Env)env)->value));
}
EUFUN_CLOSE
EUFUN_2( Fn_make_reader, class, slot)
{
LispObject desc,pos;
if (!is_class(class))
CallError(stacktop,"make-reader: non class",class,NONCONTINUABLE);
if (classof(class) == Structure_Class) {
EUCALLSET_2(desc, Fn_find_slot_description,class,slot);
EUCALLSET_1(pos, Fn_slot_description_position,desc);
if (pos == unbound)
CallError(stacktop,"make-reader: cannot-make-reader",pos,NONCONTINUABLE);
return(make_anonymous_module_env_function_2(stacktop,
(LispObject) &Module_classes,
structure_reader_template,
1,
sym_position,pos,
sym_class,class));
}
/* Most general - hacking slot-value */
return(make_anonymous_module_env_function_1(stacktop,
(LispObject) &Module_classes,
reader_template,1,
sym_nil,slot));
}
EUFUN_CLOSE
EUFUN_3( structure_writer_template, env, obj, val)
{
LispObject tmp;
if (EUCALL_2(Fn_subclassp,classof(obj),
symbol_ref(stacktop,NULL,env,sym_class)) == nil)
CallError(stacktop,"wrong class of object for writer",obj,
NONCONTINUABLE);
slotrefupdate(obj,intval(symbol_ref(stacktop,NULL,env,sym_position)),val);
return val;
}
EUFUN_CLOSE
EUFUN_3( writer_template, env, obj, val)
{
RETURN_EUCALL(EUCALL_3(Fn_slot_value_setter,obj,((Env)env)->value,val));
}
EUFUN_CLOSE
EUFUN_2( Fn_make_writer, class, slot)
{
LispObject desc, pos;
if (!is_class(class))
CallError(stacktop,"make-writer: non class",class,NONCONTINUABLE);
if (classof(class) == Structure_Class) {
EUCALLSET_2(desc, Fn_find_slot_description,class,slot);
EUCALLSET_1(pos, Fn_slot_description_position,desc);
if (pos == unbound)
CallError(stacktop,"make-writer: cannot-make-writer",pos,NONCONTINUABLE);
return(make_anonymous_module_env_function_2(stacktop,(LispObject) &Module_classes,
structure_writer_template,
2,
sym_position,pos,
sym_class,class));
}
return(make_anonymous_module_env_function_1(stacktop,
(LispObject) &Module_classes,
writer_template,2,
sym_nil,slot));
}
EUFUN_CLOSE
static EUFUN_2( predicate_template, env, obj)
{
return((EUCALL_2(Fn_subclassp,classof(obj),((Env)env)->value) == nil ?
nil : lisptrue));
}
EUFUN_CLOSE
EUFUN_1( Fn_make_predicate, class)
{
LispObject p;
if (!is_class(class))
CallError(stacktop,
"make-predicate: non-class supplied",class,NONCONTINUABLE);
p = make_anonymous_module_env_function_1(stacktop,
(LispObject) &Module_classes,
predicate_template,1,nil,class);
return(p);
}
EUFUN_CLOSE
/*
* Chris Burdorf hacks...
*/
#define is_instance(obj) (typeof(obj) == TYPE_INSTANCE)
EUFUN_1( Fn_instance_slots, inst)
{
if (!is_instance(inst))
CallError(stacktop,
"instance-slots: not a simple instance",inst,NONCONTINUABLE);
#ifdef naff /* Mon Jul 22 19:05:48 1991 */
/**/
/**/ return(inst->INSTANCE.slots);
#endif /* naff Mon Jul 22 19:05:48 1991 */
printf("Instance slots: unimplementable function\n");
return nil;
}
EUFUN_CLOSE
EUFUN_2( Fn_instance_slots_setter, inst, val)
{
if (!is_instance(inst))
CallError(stacktop,
"instance-slots: not a simple instance",inst,NONCONTINUABLE);
printf("Instance slots setter: unimplementable function\n");
return nil;
#ifdef naff /* Mon Jul 22 19:06:24 1991 */
/**/ inst->INSTANCE.slots = val;
/**/ return(inst);
#endif /* naff Mon Jul 22 19:06:24 1991 */
}
EUFUN_CLOSE
EUFUN_2( Fn_class_of_setter, obj, class)
{
printf("Setter of class-of called. Your program may now crash\n");
if (!is_instance(obj))
CallError(stacktop,
"(setter class-of): not a simple instance",obj,NONCONTINUABLE);
if (!is_class(class))
CallError(stacktop,"(setter class-of): non class",class,NONCONTINUABLE);
lval_classof(obj) = class;
return(obj);
}
EUFUN_CLOSE
/* *************************************************************** */
/* Initialisation of this module (should be seperate...) */
/* *************************************************************** */
/* Class name module stuff... */
#define CLASS_NAMES_ENTRIES 111 /* Too many */
MODULE Module_class_names;
LispObject Module_class_names_values[CLASS_NAMES_ENTRIES];
void register_class_names(LispObject *stacktop,LispObject c)
{
LispObject sub;
make_module_entry_using_symbol(stacktop,c->CLASS.name,c);
sub = c->CLASS.subclasses;
while (sub != nil) {
STACK_TMP(CDR(sub));
register_class_names(stacktop,CAR(sub));
UNSTACK_TMP(sub);
}
}
/* *************************************************************** */
/* Initialisation of this module */
/* *************************************************************** */
#define SET_ASSOC(a,b) \
{ LispObject tmp,tmp2; \
STACK_TMP(a); \
tmp2=b; \
UNSTACK_TMP(tmp); \
set_anon_associate(stacktop,tmp,tmp2); \
}
void initialise_classes(LispObject *stacktop)
{
extern void set_anon_associate(LispObject*,LispObject,LispObject);
/* Internal symbols... */
sym_direct_superclasses =get_symbol(stacktop,"direct-superclasses");
add_root(&sym_direct_superclasses);
sym_direct_slot_descriptions=get_symbol(stacktop,"direct-slot-descriptions");
add_root(&sym_direct_slot_descriptions);
sym_metaclass_hypotheses = get_symbol(stacktop,"metaclass-hypotheses");
add_root(&sym_metaclass_hypotheses);
sym_slot_class = get_symbol(stacktop,"slot-class");
add_root(&sym_slot_class);
sym_slot_initargs = get_symbol(stacktop,"slot-initargs");
add_root(&sym_slot_initargs);
sym_predicate = get_symbol(stacktop,"predicate");
add_root(&sym_predicate);
/* The class names module */
open_module(stacktop,
&Module_class_names,Module_class_names_values,
"class-names",CLASS_NAMES_ENTRIES);
register_class_names(stacktop,Object);
close_module();
/* Class operations */
open_module(stacktop,
&Module_classes,Module_classes_values,
"classes",CLASSES_ENTRIES);
/* Class object accessors... */
(void) make_module_function(stacktop,"classp",Fn_classp,1);
SET_ASSOC(make_module_function(stacktop,"class-of",Fn_class_of,1),
make_unexported_module_function(stacktop,"class-of-setter",
Fn_class_of_setter,2));
(void) make_module_function(stacktop,"subclassp",Fn_subclassp,2);
(void) make_module_function(stacktop,"class-name",Fn_class_name,1);
(void) make_module_function(stacktop,"class-prototype",Fn_class_prototype,1);
(void) make_module_function(stacktop,"class-precedence-list",
Fn_class_precedence_list,1);
(void) make_module_function(stacktop,"class-direct-superclasses",
Fn_class_direct_superclasses,1);
(void) make_module_function(stacktop,"class-direct-subclasses",
Fn_class_direct_subclasses,1);
(void) make_module_function(stacktop,"class-slot-descriptions",
Fn_class_slot_descriptions,1);
(void) make_module_function(stacktop,"class-direct-slot-descriptions",
Fn_class_direct_slot_descriptions,1);
/* Inheritance... */
generic_compute_class_precedence_list
= make_wrapped_module_generic(stacktop,"compute-class-precedence-list",1,
Gf_compute_class_precedence_list);
add_root(&generic_compute_class_precedence_list);
(void) make_module_function(stacktop,"generic_compute_class_precedence_list,Standard_Class",
Md_compute_class_precedence_list_Class,
1);
/* Slot access protocol... */
generic_slot_value_using_class
= make_module_generic(stacktop,"slot-value-using-class",3);
add_root(&generic_slot_value_using_class);
make_module_function(stacktop,"generic_slot_value_using_class,Structure_Class",
Md_slot_value_using_class_Structure_Class,
3);
make_module_function(stacktop,"generic_slot_value_using_class,Standard_Class",
Md_slot_value_using_class_Standard_Class,
3);
generic_slot_value_using_class_setter
= make_module_generic(stacktop,"(setter slot-value-using-class)",4);
add_root(&generic_slot_value_using_class_setter);
make_module_function(stacktop,"generic_slot_value_using_class_setter,StructureClass",
Md_slot_value_using_class_setter_Structure_Class,
4);
make_module_function(stacktop,"generic_slot_value_using_class_setter,Standard_Class",
Md_slot_value_using_class_setter_Standard_Class,
4);
SET_ASSOC(generic_slot_value_using_class,
generic_slot_value_using_class_setter);
generic_slot_value_using_slot_description
= make_module_generic(stacktop,"slot-value-using-slot-description",2);
add_root(&generic_slot_value_using_slot_description);
make_module_function(stacktop,"generic_slot_value_using_slot_description,Object,Local_Slot_Description",
Md_slot_value_using_slot_description_Local_Slot_Description,
2);
generic_slot_value_using_slot_description_setter
= make_module_generic(stacktop,
"(setter slot-value-using-slot-description)",3);
add_root(&generic_slot_value_using_slot_description_setter);
make_module_function(stacktop,
"generic_slot_value_using_slot_description_setter,Object,Local_Slot_Description",
Md_slot_value_using_slot_description_setter_Local_Slot_Description,
3);
SET_ASSOC(generic_slot_value_using_slot_description,
generic_slot_value_using_slot_description_setter);
generic_find_slot_description
= make_module_generic(stacktop,"find-slot-description",2);
add_root(&generic_find_slot_description);
make_module_function(stacktop,"generic_find_slot_description,Structure_Class",
Md_find_slot_description_Structure_Class,
2);
make_module_function(stacktop,"generic_find_slot_description,Standard_Class",
Md_find_slot_description_Standard_Class,
2);
SET_ASSOC(make_module_function(stacktop,"slot-value",
Fn_slot_value,2),
make_module_function(stacktop,"slot-value-setter",
Fn_slot_value_setter,3));
/* Inheritance... */
(void) make_module_function(stacktop,"add-superclasses",Fn_add_superclasses,3);
(void) make_module_function(stacktop,"add-subclass",Fn_add_subclass,2);
(void) make_module_function(stacktop,"collect-slots",Fn_collect_slots,2);
generic_make_slot_description
= make_module_generic(stacktop,"make-slot-description",2);
add_root(&generic_make_slot_description);
(void) make_module_function(stacktop,"generic_make_slot_description,Standard_Class",
Md_make_slot_description_Class,2);
generic_make_inherited_slot_description
= make_module_generic(stacktop,"make-inherited-slot-description",3);
add_root(&generic_make_inherited_slot_description);
(void) make_module_function(stacktop,
"generic_make_inherited_slot_description,Standard_Class,Slot_Description",
Md_make_inherited_slot_description_Class_Slot_Description,3
);
generic_add_slot_description = make_module_generic(stacktop,
"add-slot-description",2);
add_root(&generic_add_slot_description);
(void) make_module_function(stacktop,"generic_add_slot_description,StandardClass,SlotDescription",
Md_add_slot_description_Class_Slot_Description,2
);
(void)
make_module_function(stacktop,"generic_add_slot_description,StandardClass,LocalSlotDescription",
Md_add_slot_description_Class_Local_Slot_Description,2
);
/* GF initialisation */
generic_allocate_instance = make_module_generic(stacktop,
"allocate-instance",2);
add_root(&generic_allocate_instance);
make_module_function(stacktop,"generic_allocate_instance,StandardClass",
Md_allocate_instance_1,2);
make_module_function(stacktop,"generic_allocate_instance,StructureClass",
Md_allocate_instance_2,2);
make_module_function(stacktop,"generic_allocate_instance,Slot_Description_Class",
Md_allocate_instance_3,2);
make_module_function(stacktop,"generic_allocate_instance,Condition_Class",
Md_allocate_instance_4,2);
make_module_function(stacktop,"generic_allocate_instance,Primitive_Class",
Md_allocate_instance_Primitive_Class,
2);
generic_initialize_instance = make_module_generic(stacktop,
"initialize-instance",2);
add_root(&generic_initialize_instance);
make_module_function(stacktop,"generic_initialize_instance,Object",
Md_initialize_instance_1,2);
make_module_function(stacktop,"generic_initialize_instance,Standard_Class",
Md_initialize_instance_2,2);
make_module_function(stacktop,"generic_initialize_instance,Slot_Description",
Md_initialize_instance_3,2);
make_module_function(stacktop,"generic_initialize_instance,Default_Condition",
Md_initialize_instance_4,2);
make_module_function(stacktop,"make-instance",Gf_make_instance,-2);
make_module_function(stacktop,"make-constructor",Fn_make_constructor,1);
make_module_function(stacktop,"make-reader",Fn_make_reader,2);
make_module_function(stacktop,"make-writer",Fn_make_writer,2);
make_module_function(stacktop,"make-predicate",Fn_make_predicate,1);
SET_ASSOC(make_module_function(stacktop,"slots-of",
Fn_instance_slots,
1),
make_unexported_module_function(stacktop,"instance-slots-setter",
Fn_instance_slots_setter,
2));
initialise_slots(stacktop);
close_module();
}